'''
1、接受tessng向kafka发送的车辆数据,并进行展示


'''


import carla
import numpy as np
import time
from carla import Transform, Rotation, Location
from kafka import KafkaConsumer
import json
from pyproj import Proj


vehicle_actors = []
spawed_ids = {}

# 经纬度转xy坐标，在carla中y坐标的值需要取反
rule = Proj("+proj=tmerc +lat_0=40.04752343063863 +lon_0=116.2872228823074 +k=1 +x_0=0 +y_0=0 +datum=WGS84")



def main():
           
    try:
                     
    #  ======================================跟服务器实现连接=============================================
        client = carla.Client('localhost', 2000)
        client.set_timeout(10.0)


                
    #  ======================================使用自定义地图=============================================
        world = client.load_world('shangdiwr')
        
        # with open('/home/wanji/SDWR_UE4/PythonAPI/work00/hsy/map/TownBig.xodr', encoding='utf-8') as od_file:
        #     try:
        #         data = od_file.read()
        #     except OSError:
        #         print('file could not be readed.')
        #         sys.exit()
        # with open('/home/wanji/SDWR_UE4/PythonAPI/work00/hsy/map/SDOpenDrive.xodr', encoding='utf-8') as od_file:
        #     try:
        #         data = od_file.read()
        #     except OSError:
        #         print('file could not be readed.')
        #         sys.exit()
        # world = client.generate_opendrive_world(
        #     data, 
        #     carla.OpendriveGenerationParameters(
        #         vertex_distance=2.0, #生成的网格顶点之间距离 ，默认2.0
        #         max_road_length=1.0, 
        #         wall_height=1.0,
        #         additional_width=0.6,
        #         smooth_junctions=True,
        #         enable_mesh_visibility=True
        #     )
        # )

    # =============================天气=================================

        # 控制世界的天气和时间（太阳的位置） 万里无云，没有降雨，太阳的角度为90
        weather = carla.WeatherParameters(
            cloudiness=0.0,  # 0-100  0 是晴朗的天空，100 是完全阴天
            precipitation=0.0,  # 0 表示没有下雨，100 表示大雨
            precipitation_deposits=0.0, # 0 表示道路上没有水坑，100 表示道路完全被雨水覆盖
            wind_intensity=0.0, # 0 表示平静，100 表示强风，风会影响雨向和树叶
            sun_azimuth_angle=0.0, # 太阳方位角，0～360
            sun_altitude_angle=90.0,  # 太阳高度角，90 是中午，-90 是午夜
            fog_density=0.0, # 0～100 表示雾的浓度或厚度，仅影响RGB相机传感器
            fog_distance=0.0, # 雾开始的距离，单位为米
            wetness=0.0, # 0～100 表示道路湿度百分比，仅影响RGB相机传感器
            fog_falloff=0.0, # 雾的密度，0至无穷大，0 表示雾比空气轻，覆盖整个场景，1表示与空气一样，覆盖正常大小的建筑物
            scattering_intensity=0.0, # 控制光线对雾的穿透程度
            mie_scattering_scale=0.0, # 控制光线与花粉或空气等大颗粒的相互作用，导致天气朦胧，光源周围有光晕，0表示无影响
            rayleigh_scattering_scale=0.0331, # 控制光与空气分子等小粒子的相互作用，取决于光波长，导致白天蓝天或晚上红天
            )
        world.set_weather(weather)
        
    # =============================视角坐标=================================
        x, y = rule(116.29220138718945, 40.05073628413568)
        

        vehicle_trans11 = Transform(Location(x=x, y=-y, z=101.677723), 
                                    Rotation(pitch=-30.000000, yaw = 270, roll=0.000000))
        world.get_spectator().set_transform(vehicle_trans11)  # 设置世界视角
        
        # =============================设置车辆=================================
        
        vehicle_trans12 = Transform(Location(x=x, y=-y, z=41.677723), 
                                    Rotation(yaw = 347.65-90))
        blueprint_library = world.get_blueprint_library()
        bp1 = blueprint_library.find('vehicle.lincoln.mkz_2017')
        bp1.set_attribute('color', '0, 0, 0')
        # ego_vehicle1 = world.spawn_actor(bp1, vehicle_trans12)
    
    # =============================创建交通管理器对象，并设置仿真的倍数和车辆最大的速度=================================  
    
        traffic_manager = client.get_trafficmanager(8000)
        # traffic_manager.set_global_port(8100)
        traffic_manager.set_global_distance_to_leading_vehicle(2.0)
        traffic_manager.global_percentage_speed_difference(40.0)
        
        if True:
            settings = world.get_settings()
            traffic_manager.set_synchronous_mode(True)
            if not settings.synchronous_mode:
                print("开启异步模式")
                synchronous_master = True
                settings.synchronous_mode = False
                settings.fixed_delta_seconds = 0.1
                world.apply_settings(settings)
            else:
                synchronous_master = False
                
    
   
    # =============================创建kafka消费者=================================
        topic = 'tess_send_carla_shangdi'
        bootstrap_servers = '106.120.201.126:14576'
        # 创建Kafka消费者实例
        consumer = KafkaConsumer(
            topic,
            bootstrap_servers = bootstrap_servers,
            value_deserializer=lambda x: json.loads(x.decode('utf-8'))  # 指定反序列化函数为JSON解析
        )


        # 持续消费消息
        while True:
        
            for message in consumer:
                # 解析Kafka消息中的车辆位置信息
                json_string = message.value
                # print(json_string)
                participants = json_string["participants"]
                # print(participants)
                # time.sleep(3)
                errorids = []
                nowids = []
                for p in participants:
                    nowids.append(p["ID"])
                #添加交通流
                for par in participants:

                    x, y = rule(par["longitude"], par["latitude"])
                    
                    trans = Transform(carla.Location(x=x, y=-y, z=37),
                                        carla.Rotation(yaw= par["courseAngle"]-90))
                    
                    print(par["courseAngle"])
                    vehtype = par['type']
                    vehtype = 'vehicle.lincoln.mkz_2017'
                    id = par['ID']
                    
                    if id not in spawed_ids.keys():
                        bp1 = world.get_blueprint_library().find(vehtype)
                        try:
                            bp1.set_attribute('color', '0,0,0')
                        except:
                            pass
                        else:
                            pass

                        if vehtype == 'vehicle.lincoln.mkz_2017':
                            batch = [
                                carla.command.SpawnActor(bp1, trans).then(
                                    carla.command.SetSimulatePhysics(carla.command.FutureActor, False))
                            ]
                            response = client.apply_batch_sync(batch, False)[0]
                            if response.error:
                                errorids.append(id)
                            else:
                                spawed_ids[id] = response.actor_id
                        else:
                            batch = [
                                carla.command.SpawnActor(bp1, trans).then(
                                    carla.command.SetSimulatePhysics(carla.command.FutureActor, False))
                            ]
                            response = client.apply_batch_sync(batch, False)[0]
                            if response.error:
                                errorids.append(id)
                            else:
                                spawed_ids[id] = response.actor_id
        
                    else:
                        if vehtype == 'vehicle.lincoln.mkz_2017':
                            cid = spawed_ids[id]
                            cactor = world.get_actor(cid)
                            cactor.set_transform(trans)
                        else:
                            carlaid = spawed_ids[id]
                            vehicle = world.get_actor(carlaid)
                            if vehicle is not None:
                                vehicle.set_transform(trans)
                print("已有：", len(spawed_ids))

                destodyed_ids = [id for id in spawed_ids if id not in nowids]
                for did in destodyed_ids:
                    carlaid = spawed_ids[did]
                    vehicle = world.get_actor(carlaid)

                    if vehicle is not None:
                        vehicle.destroy()
                    del spawed_ids[did]
                print("更新：", len(nowids), "销毁:", len(destodyed_ids))
                # print(errorids)          

                print("    Some of the sensor information is missed")           
    finally:


        for sensor in spawed_ids:
            sensor.destroy()
        for actor in spawed_ids:
            if actor.is_alive:
                actor.destroy()
        # 停止并清除交通管理器
        # traffic_manager.global_percentage_speed_difference(-100.0)
        # traffic_manager.shutdown()
        # print("All cleaned up!")
        time.sleep(0.1)

                   
   
 
            
      
            
           
     

if __name__ == "__main__":
    

    
    
    
    try:
        main()
    except KeyboardInterrupt:
        print(' - Exited by user.')
